#ifndef _PIGOS_PROTECT_H_
#define _PIGOS_PROTECT_H_

#include <type.h>

#define	PRIVILEGE_KRNL	0
#define	PRIVILEGE_USER	3

struct descriptor {
	u16_t	limit_low;
	u16_t	base_low;
	u8_t	base_mid;
	u8_t	attr1;			/* P(1) DPL(2) DT(1) TYPE(4) */
	u8_t	limit_high_attr2;	/* G(1) D(1) 0(1) AVL(1) LimitHigh(4) */
	u8_t	base_high;
};

struct gate {
	u16_t	offset_low;
	u16_t	selector;
	u8_t	dcount;
	u8_t	attr;			/* P(1) DPL(2) DT(1) TYPE(4) */
	u16_t	offset_high;
};

struct tss {
	u16_t	next;
	u16_t	zero0;
	u32_t	esp0;
	u16_t	ss0;
	u16_t	zero1;
	u32_t	esp1;
	u16_t	ss1;
	u16_t	zero2;
	u32_t	esp2;
	u16_t	ss2;
	u16_t	zero3;
	u32_t	cr3_pdbr;
	u32_t	eip;
	u32_t	eflags;
	u32_t	eax;
	u32_t	ecx;
	u32_t	edx;
	u32_t	ebx;
	u32_t	esp;
	u32_t	ebp;
	u32_t	esi;
	u32_t	edi;
	u16_t	es;
	u16_t	zero4;
	u16_t	cs;
	u16_t	zero5;
	u16_t	ss;
	u16_t	zero6;
	u16_t	ds;
	u16_t	zero7;
	u16_t	fs;
	u16_t	zero8;
	u16_t	gs;
	u16_t	zero9;
	u16_t	ldt_selector;
	u16_t	zero10;
	u32_t	io_map;
};

struct ldt {
	struct descriptor	zero;
	struct descriptor	cs;
	struct descriptor	ds;
	struct descriptor	ss;
	struct descriptor	ss_kernel;
};


/* Index of GDT. */
#define	INDEX_GDT_DUMMY		0
#define	INDEX_GDT_FLAT_C	1
#define	INDEX_GDT_FLAT_RW	2
#define	INDEX_GDT_VIDEO		3
#define INDEX_GDT_TSS		5
#define INDEX_GDT_LDT		6

/* Selectors of GDT: index*8 + RPL */
#define	SELECTOR_DUMMY		INDEX_GDT_DUMMY * 8
#define	SELECTOR_FLAT_C		INDEX_GDT_FLAT_C * 8	
#define	SELECTOR_FLAT_RW	INDEX_GDT_FLAT_RW * 8
#define	SELECTOR_VIDEO		INDEX_GDT_VIDEO * 8 + 3	// RPL=3
#define SELECTOR_TSS		INDEX_GDT_TSS * 8 + 3
#define SELECTOR_LDT		INDEX_GDT_LDT * 8 + 3

#define	SELECTOR_KERNEL_CS	SELECTOR_FLAT_C
#define	SELECTOR_KERNEL_DS	SELECTOR_FLAT_RW

/* Selectors of LDT. */
#define SELECTOR_USER_CODE	8 + SA_RPL3 + SA_TIL
#define SELECTOR_USER_DATA	16 + SA_RPL3 + SA_TIL
#define SELECTOR_USER_STACK	24 + SA_RPL3 + SA_TIL
#define SELECTOR_USER_STACK_K	32 + SA_TIL

/* Attributes. */
/* 描述符类型值说明 */
#define	DA_32			0x4000	/* 32 位段				*/
#define	DA_LIMIT_4K		0x8000	/* 段界限粒度为 4K 字节			*/
#define	DA_DPL0			0x00	/* DPL = 0				*/
#define	DA_DPL1			0x20	/* DPL = 1				*/
#define	DA_DPL2			0x40	/* DPL = 2				*/
#define	DA_DPL3			0x60	/* DPL = 3				*/
/* 存储段描述符类型值说明 */
#define	DA_DR			0x90	/* 存在的只读数据段类型值		*/
#define	DA_DRW			0x92	/* 存在的可读写数据段属性值		*/
#define	DA_DRWA			0x93	/* 存在的已访问可读写数据段类型值	*/
#define	DA_C			0x98	/* 存在的只执行代码段属性值		*/
#define	DA_CR			0x9A	/* 存在的可执行可读代码段属性值		*/
#define	DA_CCO			0x9C	/* 存在的只执行一致代码段属性值		*/
#define	DA_CCOR			0x9E	/* 存在的可执行可读一致代码段属性值	*/
/* 系统段描述符类型值说明 */
#define	DA_LDT			0x82	/* 局部描述符表段类型值			*/
#define	DA_TaskGate		0x85	/* 任务门类型值				*/
#define	DA_386TSS		0x89	/* 可用 386 任务状态段类型值		*/
#define	DA_386CGate		0x8C	/* 386 调用门类型值			*/
#define	DA_386IGate		0x8E	/* 386 中断门类型值			*/
#define	DA_386TGate		0x8F	/* 386 陷阱门类型值			*/

#define SA_RPL0			0
#define SA_RPL1			1
#define SA_RPL2			2
#define SA_RPL3			3

#define SA_TIG			0
#define SA_TIL			4


#endif
